///////////zjtopspeed
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;

namespace GetAllFilesOfAFolder
{
    public partial class Main : Form
    {
        private Int64 fileCount = 0;
        private const string pathSeperator = "\\";
        // file count to be copied
        private int leftSourceFileCount = 0;
        private int rightSourceFileCount = 0;
        private string strSelectedPaht = string.Empty;
        private string leftPath = string.Empty;
        private string rightPath = string.Empty;
        Dictionary<string, string> commonList = new Dictionary<string, string>();
        Dictionary<string, string> leftList = new Dictionary<string, string>();
        Dictionary<string, string> rightList = new Dictionary<string, string>();
        List<string> temp = new List<string>();

        // after compare and delete same files, file need to be copied to right path from left
        List<string> LeftToRightCopyingList = new List<string>();

        // after compare and delete same files, file need to be copied to left path from right
        List<string> RightToLeftCopyingList = new List<string>();

        public Main()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
        }
        public void GetAllDirList(DirectoryInfo directory, Dictionary<string, string> list)
        {
            try
            {
                DirectoryInfo[] directoies = directory.GetDirectories();
                foreach (DirectoryInfo subDirectory in directoies)
                {
                    GetAllDirList(subDirectory, list);
                }
                FileInfo[] files = directory.GetFiles();

                // if folder is empty and not the fold itself, also add to copy list
                if (files.Length == 0)
                {
                    string a = directory.FullName.Substring(
                                strSelectedPaht.Length,
                                directory.FullName.Length - strSelectedPaht.Length);

                    // empty topest folder,should not be added
                    // e.g. copy "c:\folder" to "d:\folder"
                    if (a.Length != 0)
                    {
                        list.Add(a, a);
                    }
                }
                foreach (FileInfo file in files)
                {
                    if (!file.FullName.Contains("$"))
                    {
                        string a = file.FullName.Substring(
                                strSelectedPaht.Length,
                                file.FullName.Length - strSelectedPaht.Length);
                        list.Add(a, a);
                    }
                }
            }
            catch (Exception)
            {

            }
        }

        private void btnCompare_Click(object sender, EventArgs e)
        {
            CompareFileLists();
        }

        private void CompareFileLists()
        {
            foreach (KeyValuePair<string, string> s in leftList)
            {
                temp.Add(s.Value);
            }
            foreach (KeyValuePair<string, string> kvpL in leftList)
            {
                foreach (KeyValuePair<string, string> kvpR in rightList)
                {
                    if (kvpL.Key == kvpR.Key)
                    {
                        lbLeft.Items.Remove(kvpR.Value);
                        lbRight.Items.Remove(kvpR.Value);
                        temp.Remove(kvpL.Value);
                    }
                }
            }
            foreach (object item in lbLeft.Items)
            {
                LeftToRightCopyingList.Add(item.ToString());
            }
            leftSourceFileCount = lbLeft.Items.Count;
            lblLeftCount.Text = leftSourceFileCount.ToString();

            foreach (object item in lbRight.Items)
            {
                RightToLeftCopyingList.Add(item.ToString());
            }
            rightSourceFileCount = lbRight.Items.Count;
            lblRightCount.Text = rightSourceFileCount.ToString();
        }


        private void btnBrowseL_Click(object sender, EventArgs e)
        {
            //folderBrowserDialog1.Reset();
            lbLeft.Items.Clear();
            DialogResult dr = folderBrowserDialog1.ShowDialog();
            if (dr == DialogResult.OK)
            {
                txtPathL.Text = folderBrowserDialog1.SelectedPath;
                string path = folderBrowserDialog1.SelectedPath;
                strSelectedPaht = folderBrowserDialog1.SelectedPath;
                GetAllDirList(new DirectoryInfo(path), leftList);
                lbLeft.BeginUpdate();
                foreach (KeyValuePair<string, string> kvp in leftList)
                {
                    lbLeft.Items.Add(kvp.Value);
                }
                lbLeft.EndUpdate();
                lblLeftCount.Text = lbLeft.Items.Count.ToString();
            }

        }

        private void btnBrowseR_Click(object sender, EventArgs e)
        {
            //folderBrowserDialog1.Reset();
            lbRight.Items.Clear();
            DialogResult dr = folderBrowserDialog1.ShowDialog();
            if (dr == DialogResult.OK)
            {
                txtPathR.Text = folderBrowserDialog1.SelectedPath;
                string path = folderBrowserDialog1.SelectedPath;
                strSelectedPaht = folderBrowserDialog1.SelectedPath;
                GetAllDirList(new DirectoryInfo(path), rightList);
                lbRight.BeginUpdate();
                foreach (KeyValuePair<string, string> kvp in rightList)
                {
                    lbRight.Items.Add(kvp.Value);
                }
                lbRight.EndUpdate();
                lblRightCount.Text = lbRight.Items.Count.ToString();
            }
        }

        private void btnSyncToRight_Click(object sender, EventArgs e)
        {
            // copy all file under "e:\source\" to "f:\destination\"
            bgwArgument bgwa = new bgwArgument();
            bgwa.SourcePath = txtPathL.Text;
            bgwa.DestinationPath = txtPathR.Text;
            bgwa.CopySource = LeftToRightCopyingList;
            if (bgwFileCopyToRight.IsBusy == false)
            {
                bgwFileCopyToRight.RunWorkerAsync(bgwa);
            }
        }

        private void BtnSyncToLeft_Click(object sender, EventArgs e)
        {
            // copy all file under "e:\source\" to "f:\destination\"
            bgwArgument bgwa = new bgwArgument();
            bgwa.SourcePath = txtPathR.Text;
            bgwa.DestinationPath = txtPathL.Text;
            bgwa.CopySource = RightToLeftCopyingList;
            if (bgwFileCopyToLeft.IsBusy == false)
            {
                bgwFileCopyToLeft.RunWorkerAsync(bgwa);
            }
        }

        // bi-direction sync
        private void btnSync_Click(object sender, EventArgs e)
        {
            // copy all file under "e:\source\" to "f:\destination\"
            bgwArgument bgwa = new bgwArgument();
            bgwa.SourcePath = txtPathL.Text;
            bgwa.DestinationPath = txtPathR.Text;
            bgwa.CopySource = LeftToRightCopyingList;
            if (bgwFileCopyToRight.IsBusy == false)
            {
                bgwFileCopyToRight.RunWorkerAsync(bgwa);
            }
            bgwArgument bgwa1 = new bgwArgument();
            bgwa1.SourcePath = txtPathR.Text;
            bgwa1.DestinationPath = txtPathL.Text;
            bgwa1.CopySource = RightToLeftCopyingList;
            if (bgwFileCopyToLeft.IsBusy == false)
            {
                bgwFileCopyToLeft.RunWorkerAsync(bgwa1);
            }
        }

        private void bgwFileCopyToRight_DoWork(object sender, DoWorkEventArgs e)
        {
            bgwArgument bgwa = (bgwArgument)e.Argument;
            e.Result = Sync(bgwa.SourcePath, bgwa.DestinationPath, bgwa.CopySource, bgwFileCopyToRight);
        }

        private void bgwFileCopyToLeft_DoWork(object sender, DoWorkEventArgs e)
        {
            bgwArgument bgwa = (bgwArgument)e.Argument;
            e.Result = Sync(bgwa.SourcePath, bgwa.DestinationPath, bgwa.CopySource, bgwFileCopyToLeft);
        }

        private void bgwFileCopyToRight_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //MessageBox.Show("l down");
        }

        private void bgwFileCopyToLeft_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //MessageBox.Show("r down");
        }

        private void bgwFileCopyToRight_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            CopyInfo ci = (CopyInfo)e.UserState;
            lblLeftCount.Text = ci.CopyiedCount.ToString() + " of " + leftSourceFileCount;
            lbLeft.Items.Remove(ci.JustCopiedItem);
        }

        private void bgwFileCopyToLeft_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            CopyInfo ci = (CopyInfo)e.UserState;
            lblRightCount.Text = ci.CopyiedCount.ToString() + " of " + rightSourceFileCount;
            lbRight.Items.Remove(ci.JustCopiedItem);
        }

        private bool Sync(string source, string destination, List<string> copySource, BackgroundWorker worker)
        {
            int copiedCount = 0;
            copySource.ForEach(delegate(string pathUnderSourceFolder)
            {
                try
                {
                // complete source path, like "e:\source\folder\my.txt"
                string completeSourcePath = source + pathUnderSourceFolder;
                string folderName = string.Empty;
                string fileOrFolderName = string.Empty;

                // contain folders, like "\folder\my.txt" or "\folder\folder1"
                if (pathUnderSourceFolder.Contains(pathSeperator))
                {
                    // get folder name, "folder"
                    folderName = pathUnderSourceFolder.Substring(1, pathUnderSourceFolder.LastIndexOf(pathSeperator));

                    //destination folder name like "f:\destination\folder"
                    string destinationFolder = destination + pathSeperator + folderName;

                    //file name, like "my.txt" and it maybe a folder like "folder1"
                    fileOrFolderName = pathUnderSourceFolder.Substring(pathUnderSourceFolder.LastIndexOf(pathSeperator) + 1);
                    if (System.IO.Directory.Exists(destinationFolder) == false)
                    {
                        System.IO.DirectoryInfo fo = new DirectoryInfo(destinationFolder);
                        System.IO.Directory.CreateDirectory(destinationFolder);
                    }
                }

                // destination file or empty folder to copy
                //like "f:\destination\folder\my.txt"
                //or "f:\destination\folder\folder1"
                string destinationPath = destination + pathSeperator + folderName + fileOrFolderName;

                //if it is an empty folder, create an empty folder
                if (System.IO.File.Exists(completeSourcePath))
                {
                    System.IO.File.Copy(completeSourcePath, destinationPath, true);
                    copiedCount++;
                }

                // if is a file, copy 
                else if (System.IO.Directory.Exists(completeSourcePath))
                {
                    System.IO.Directory.CreateDirectory(destinationPath);
                    copiedCount++;
                }
                CopyInfo ci = new CopyInfo();
                ci.CopyiedCount = copiedCount;
                ci.JustCopiedItem = pathUnderSourceFolder;
                worker.ReportProgress(0, ci);
            }
            catch (Exception exx)
            {
                throw exx;
            }
            });
            return true;
        }

        private void btnSaveRight_Click(object sender, EventArgs e)
        {
            DialogResult dr = sfdFileList.ShowDialog();
            if (dr == DialogResult.OK)
            {
                System.IO.TextWriter tw = new StreamWriter(sfdFileList.FileName);
                foreach (object item in lbRight.Items)
                {
                    tw.WriteLine(item.ToString());
                }
                tw.Close();
            }
        }

        private void btnload_Click(object sender, EventArgs e)
        {
            DialogResult dr = ofdFileList.ShowDialog();
            if (dr == DialogResult.OK)
            {
                string fileName = ofdFileList.FileName;
                FileInfo fi = new FileInfo(fileName);
                string savePath = fi.DirectoryName + "\\NewFilesSavedHere";
                DirectoryInfo di = new DirectoryInfo(savePath);
                if (di.Exists == false)
                {
                    Directory.CreateDirectory(savePath);
                }
                folderBrowserDialog1.SelectedPath = savePath;
                txtPathR.Text = savePath;
                TextReader tr = new StreamReader(ofdFileList.FileName);
                string aLine = string.Empty;
                lbRight.BeginUpdate();
                while (true)
                {
                    aLine = tr.ReadLine();
                    if (aLine == null)
                    {
                        break;
                    }
                    lbRight.Items.Add(aLine);
                    rightList.Add(aLine, aLine);
                }
                lbRight.EndUpdate();
                tr.Close();
                lblRightCount.Text = lbRight.Items.Count.ToString();
            }
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }
}